package com.example.wac.util;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.example.wac.enums.ErrorCode;
import com.example.wac.enums.FileTypeEnum;
import com.example.wac.vo.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Date;
import java.util.Objects;

/**
 * oss工具类 其他复杂接口详见 https://help.aliyun.com/document_detail/32007.html
 * @author wuancheng
 */
@Slf4j
public class OssUtil {

    private static String endpoint = "http://oss-cn-shenzhen.aliyuncs.com";

    private static String urlPrefix = "https://wac-oss.oss-cn-shenzhen.aliyuncs.com/";

    private static String urlPrefixImage = "https://wac-oss.oss-cn-shenzhen.aliyuncs.com/image/";

    private static String accessKeyId = "LTAI5tR5w8Dhf5dQmidn79Wm";

    private static String accessKeySecret = "pdqpbngsq8LQ1IF5BqRymZKi64fC07";

    private static String bucketName = "wac-oss";

    /**
     * 允许上传的文件格式
     */
    private static final String[] FILE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".gif", ".png",".txt","xlxs"};


    /**
     * 公共读时的上传文件
     *
     * @param file
     * @return 返回下载文件的url链接地址
     */
    public static ApiResult uploadFile(MultipartFile file){
        String path = imageVerify(file);
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 上传的文件名
        String fileName = file.getOriginalFilename();
        // 目录名+文件名
        String filePath = path + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + fileName;
        try {
            ossClient.putObject(bucketName, filePath, new ByteArrayInputStream(file.getBytes()));
            // https://wac-oss.oss-cn-shenzhen.aliyuncs.com + /image/20220117162616422wac.jpg
            return ApiResult.success(urlPrefix+filePath);
        } catch (IOException e) {
            e.printStackTrace();
            throw ErrorCode.IMAGE_UPLOAD_ERROR.getAppException();
        }finally {
            ossClient.shutdown();
        }
    }

    /**
     * 公共读时的上传文件
     *
     * @param file
     * @return 返回预览文件的url链接地址
     */
    public static ApiResult previewUploadFile(MultipartFile file){
        String path = imageVerify(file);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 上传的文件名
        String fileName = file.getOriginalFilename();
        String filePath = path + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + fileName;
        try {
            // 设置为指定ContentType后可直接预览
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(previewTransform(fileName));
            ossClient.putObject(bucketName, filePath, new ByteArrayInputStream(file.getBytes()),metadata);
            // https://wac-oss.oss-cn-shenzhen.aliyuncs.com + /20220117162616422wac.jpg
            return ApiResult.success(urlPrefix+filePath);
        } catch (IOException e) {
            e.printStackTrace();
            throw ErrorCode.IMAGE_UPLOAD_ERROR.getAppException();
        }finally {
            ossClient.shutdown();
        }
    }


    /**
     * Excel直接上传至oss
     *
     * @param excelFilePath excel目录及文件名
     * @param ossFilePath oss上传目录及文件名
     * @param data
     * @return
     */
    public static ApiResult uploadExcel(String excelFilePath, String ossFilePath, Object data){
        OSS ossClient = null;
        try(InputStream inputStream = EasyExcelUtils.class.getClassLoader().getResourceAsStream(excelFilePath);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            EasyExcel.write(outputStream).withTemplate(inputStream).sheet().doFill(data);
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            metadata.setContentType("application/vnd.ms-excel");
            ossClient.putObject(bucketName, ossFilePath, new ByteArrayInputStream(outputStream.toByteArray()),metadata);
            return ApiResult.success(urlPrefix+ossFilePath);
        }catch (Exception e){
            throw ErrorCode.IMAGE_UPLOAD_ERROR.getAppException();
        }finally {
            ossClient.shutdown();
        }
    }

    /**
     * 检查文件是否存在
     *
     * @param ossFilePath
     * @return
     */
    public static ApiResult fileFlag(String ossFilePath){
        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            // 检查文件是否存在 doesObjectExist(String bucketName, String key) key为文件的全路径名称
            boolean exist = ossClient.doesObjectExist(bucketName, ossFilePath);
            if (exist){
                return ApiResult.success(urlPrefix+ossFilePath);
            } else {
                throw ErrorCode.FILE_DOES_NOT_EXIST.getAppException();
            }
        }finally {
            if (ossClient != null){
                ossClient.shutdown();
            }
        }
    }

    /**
     * 下载文件至本地
     *
     * @param fileName 不包含Bucket名称在内的Object完整路径
     * @return
     */
    public static ApiResult downLoadFile(String fileName){
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.getObject(new GetObjectRequest(bucketName, fileName), new File("D:\\File\\test.txt"));
        ossClient.shutdown();
        return ApiResult.success();
    }

    /**
     * 对上传的文件后缀做检验
     *
     * @param file
     * @return
     */
    private static String imageVerify(MultipartFile file){
        // 对上传的文件的后缀名进行校验
        FileTypeEnum[] typeEnum = FileTypeEnum.values();
        for (FileTypeEnum type : typeEnum) {
            if (StringUtils.endsWithIgnoreCase(file.getOriginalFilename(),type.getSuffix())){
                 if (Objects.equals(type.getType(),"image")){
                     return "image/";
                 }else {
                     return "";
                 }

            }
        }
        throw ErrorCode.IMAGE_TYPE_ERROR.getAppException();
    }

    /**
     * 获取预览的setContentType类型
     *
     * @param fileName
     * @return
     */
    public static String previewTransform(String fileName){
        String fileNameSuffix = fileName.substring(fileName.lastIndexOf(".")+1);
        FileTypeEnum[] typeEnum = FileTypeEnum.values();
        for (FileTypeEnum type : typeEnum) {
            if (type.getSuffix().equalsIgnoreCase(fileNameSuffix)){
                // image/png
                return type.getType() + "/" + StringUtils.substring(type.getSuffix(),0);
            }
        }
        throw ErrorCode.IMAGE_TYPE_ERROR.getAppException();
    }

}
